import { Controller, Get, Param, ParseIntPipe, Post, Res, UploadedFile, UseGuards, UseInterceptors, StreamableFile, Query, BadRequestException } from '@nestjs/common';
import { AvatarInterceptor } from '../interceptors/avatar.interceptor';
import { Express, Response } from 'express';
import { ApiOperation, ApiTags, ApiConsumes, ApiBody, ApiProperty, ApiBearerAuth } from '@nestjs/swagger'
import { AuthJwtGuard } from '@/auth/modules/jwt/guards/auth-jwt.guard';
import { CurrentUser } from '@/auth/decorators/current.decorator';
import { UserEntity } from '@/user/entities/user.mysql.entity';
import { CommandBus, QueryBus } from '@nestjs/cqrs';
import { CreateAvatarCommand } from '../commands/create-avatar.command';
import { AvatarService } from '../providers/avatar.service';
import { GetUserAvatarQuery } from '../queries/get-user-avatar.query';


class FileUploadDto {
  @ApiProperty({ type: 'string', format: 'binary' })
  avatar: any
}

@Controller('')
@ApiTags('用户头像')
export class AvatarController {

  constructor(
    private readonly commandBus: CommandBus,
    private readonly queryBus: QueryBus,
    private readonly avatarService: AvatarService
  ) { }

  /**
   * 用户上传头像接口
   */
  @Post('avatar')
  @ApiBearerAuth()
  @ApiOperation({ summary: '上传用户头像' })
  @UseGuards(AuthJwtGuard)
  @UseInterceptors(AvatarInterceptor)
  @ApiConsumes('multipart/form-data')
  @ApiBody({ type: FileUploadDto, description: "上传文件" })
  createAvatar(@UploadedFile() file: Express.Multer.File, @CurrentUser() user: UserEntity) {
    const { filename, mimetype, size } = file

    return this.commandBus.execute(new CreateAvatarCommand({
      filename,
      mimetype,
      size,
      userId: user.id
    }))
  }

  /**
   * 用户查询头像接口
   */
  @ApiOperation({ summary: '查询用户头像' })
  @ApiProperty({ name: 'userId', type: 'number', example: 1 })
  @Get('users/:userId/avatar')
  // @Header('Content-Type', 'application/json') 另外一种方法
  async getUserAvatar(
    @Param('userId', ParseIntPipe) userId: number,
    // Express 设置完头部后如果还需要交给nest处理 需要开启 passthrough
    // 或者使用 @Headers装饰器就不用这么麻烦
    @Res({ passthrough: true }) res: Response,
    @Query('size') size: string
  ) {
    if (!size) {
      throw new BadRequestException('请选择头像尺寸')
    }
    const isValidSize = ['large', 'medium', 'small'].some(item => item === size)
    if (!isValidSize) {
      throw new BadRequestException('无效的尺寸参数')
    }
    const avatar = await this.queryBus.execute(new GetUserAvatarQuery({ userId }))
    const avatarStream = this.avatarService.getUserAvatarStream(avatar.filename, size)
    res.set({
      'Content-Type': avatar.mimetype,
    })

    return new StreamableFile(avatarStream)
  }

}
